package main

import (
	"fmt"
	"os"
	"syscall"
	"time"
)

func main() {
	const name = "demo.lock"

	// 场景 1：排他锁（写锁）—— 阻塞版本
	fd, err := syscall.Open(name, os.O_CREATE|os.O_RDWR, 0644)
	if err != nil {
		panic(err)
	}
	fmt.Println("【1】尝试加排他锁 LOCK_EX …")
	if err := syscall.Flock(fd, syscall.LOCK_EX); err != nil {
		panic(err)
	}
	fmt.Println("【1】排他锁加锁成功，模拟写操作 3 s")
	time.Sleep(3 * time.Second)

	// 场景 2：手动释放锁
	fmt.Println("【2】手动释放锁 LOCK_UN")
	if err := syscall.Flock(fd, syscall.LOCK_UN); err != nil {
		panic(err)
	}

	// 场景 3：共享锁（读锁）
	fmt.Println("【3】加共享锁 LOCK_SH")
	if err := syscall.Flock(fd, syscall.LOCK_SH); err != nil {
		panic(err)
	}
	fmt.Println("【3】共享锁成功，模拟读操作 2 s")
	time.Sleep(2 * time.Second)

	// 场景 4：非阻塞加排他锁（LOCK_EX|LOCK_NB）
	fmt.Println("【4】尝试非阻塞排他锁 LOCK_EX|LOCK_NB")
	err = syscall.Flock(fd, syscall.LOCK_EX|syscall.LOCK_NB)
	if err == syscall.EWOULDBLOCK {
		fmt.Println("【4】返回 EWOULDBLOCK，锁被占用")
	} else if err != nil {
		panic(err)
	} else {
		fmt.Println("【4】非阻塞排他锁成功（前面已释放）")
	}

	// 场景 5：关闭 fd 自动释放锁
	fmt.Println("【5】关闭 fd，flock 自动释放")
	syscall.Close(fd)
	fmt.Println("【5】fd 已关闭，锁随之消失")
}

